package controller;

import java.awt.Component;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;

import util.ContentManager;
import view.GameWindow;
import view.FullScreen;
import model.BallPiece;
import model.EmptyPiece;
import model.GameBoard;
import model.Level;
import model.Piece;
import model.RestrictedPiece;
import model.SelectedBallPiece;

public class GameController implements IGameController {
	/* The game board */
	private GameBoard gameBoard;
	/* The game window */
	private GameWindow gameWindow;
	/* Solitaire core (used for full screen) */
	private FullScreen fullScreen;

	/** Constructs a new solitaire game */
	public GameController() {
	}
	
	/** Initializes the game objects */
	public void init() {
		// Load resources
		this.loadResources();
		
		// Initialize the game board
		this.gameBoard = new GameBoard();
		this.gameBoard.setLevel(Level.getLevel1());
		
		// Default to windowed mode
		this.runWindowed();
	}
	
	/** Loads external resources used by the game */
	public void loadResources() {
		try
		{
			BallPiece.image = ContentManager.loadImage("./resources/pictures/ball.png");
			SelectedBallPiece.image = ContentManager.loadImage("./resources/pictures/ballSelected.png");
			EmptyPiece.image = ContentManager.loadImage("./resources/pictures/empty.png");
			RestrictedPiece.image = ContentManager.loadImage("./resources/pictures/restricted.png");
		}
		catch (Exception e)
		{
			System.out.println(e.getMessage());
		}
	}
	
	/** Runs the game in windowed mode */
	public void runWindowed() {
		// Get rid of full screen if available
		if (this.fullScreen != null) {
			this.fullScreen.stop();
			this.fullScreen = null;
		}
		
		// Create game window
		this.gameWindow = new GameWindow(this);
		this.gameWindow.setVisible(true);
		// TODO add listener
		//this.gameWindow.addComponentListener(new WindowResizedListener());
	}
	
	/** Runs the game full screen */
	public void runFullScreen() {
		// Get rid of windowed screen if available
		if (this.gameWindow != null) {
			this.gameWindow = null;
		}
		
		// Create full screen window
		this.fullScreen = new FullScreen(this);
		this.fullScreen.run();
	}
	
	/** Handles mouse click events */
	@Override
	public void handleMouseClick (MouseEvent e) {
		// Retrieve row and column data based on position of mouse
		int row = e.getY() / Piece.height;
		int col = e.getX() / Piece.width;
		
		// Make sure we're not clicking outside of the playing area
		if (row >= this.gameBoard.getRowLength() || col >= this.gameBoard.getColLength()) {
			return;
		}
		
		// Get value of selected piece
		int val = this.gameBoard.getCellValue(row, col);
		
		// Decide what to do based on piece found
		switch(val) {
			case 0:
				if (this.gameBoard.hasSelection()) {
					this.gameBoard.moveSelectedPieceTo(row, col);
				}
				this.gameWindow.repaint();
				break;
			case 1:
				this.gameBoard.setSelection(row, col);
				this.gameWindow.repaint();
				break;
			case 2:
				this.gameBoard.clearSelection();
				this.gameWindow.repaint();
				break;
			default:
				break;
		}
	}
	
	/** Handles window resize events */
	public void handleWindowResize (ComponentEvent e) {
		Component c = (Component)e.getSource();
		
		// Get component width & height
		int sHeight = c.getWidth();
		int sWidth = c.getHeight();
		
		// Adjust piece dimensions to width 
		if (sWidth < sHeight) {
			sHeight = sWidth;
			Piece.width = sWidth / this.gameBoard.getColLength();
			Piece.height = Piece.width;
		}
		
		// Adjust piece dimensions to height
		if (sHeight < sWidth) {
			sWidth = sHeight;
			Piece.height = sHeight / this.gameBoard.getRowLength();
			Piece.width = Piece.height;
		}
	}
	
	/** Returns the game context */
	@Override
	public IGameContext getContext() {
		return this.gameBoard;
	}

	@Override
	public void renderImages() {
		// TODO Auto-generated method stub
	}

	@Override
	public void renderShapes() {
		// TODO Auto-generated method stub
	}

	@Override
	public void resetGame() {
		// TODO Auto-generated method stub
	}

	@Override
	public void undoLastMove() {
		// TODO Auto-generated method stub
	}

	@Override
	public void quit() {
		// TODO Auto-generated method stub
	}
}